<?xml version="1.0" encoding="utf-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
  "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title>Security</title>
  <link href="../Styles/stylesheet.css" rel="stylesheet" type="text/css" />
  <script src="../toc.js" type="text/javascript">



  //<![CDATA[

   <!-- empty -->
  //]]>
  </script>
  <script type="text/javascript">




  /* <![CDATA[ */
    (function() {
        var s = document.createElement("script"), t = document.getElementsByTagName("script")[0];
        s.type = "text/javascript";
        s.async = true;
        s.src = "http://api.flattr.com/js/0.6/load.js?mode=auto";
        t.parentNode.insertBefore(s, t);
    })();
  /* ]]> */
  </script>
  <style type="text/css">
/*<![CDATA[*/

  body { counter-reset: chapter 7; }

  a.sgc-8 {display:none;}
  span.sgc-7 {color: darkmagenta}
  span.sgc-6 {color: black}
  span.sgc-5 {color: green}
  span.sgc-4 {color: blue}
  span.sgc-3 {color: DarkRed}
  span.sgc-2 {color: purple}
  span.sgc-1 {color: firebrick}
  /*]]>*/
  </style>
</head>

<body>
  <div class="chapter">
    <h1 class="en"> Security </h1>
    <h1 class="zh"> 安全 </h1>
  </div>

  <div class="preface"></div>

  <div class="generate_from_h2" id="generated-toc"></div>

  <h2 id="heading_toc_j_0" tabindex="-1" class="en">Introduction</h2>
<h2 id="heading_toc_j_0" tabindex="-1"  class="zh">简介</h2>
<p class="en">
  Although the internet was originally designed as a system to withstand
  atacks by hostile agents, it developed in a co-operative environment
  of relatively trusted entities. Alas, those days are long gone.
  Spam mail, denial of service attacks, phishing attempts and so on
  are indicative that anyone using the internet does so at their own
  risk.
</p>
<p class="zh">
尽管互联网最初被设计为可以承受敌对代理攻击的系统，但它过去一直是在一个可信的实体和合作的环境中发展起来的。可惜现在已经时过境迁。垃圾邮件，拒绝服务攻击，网络钓鱼这些东西使得每一个上网者都需要自行承担风险。
</p>
<p class="en">
  Applications have to be built to work correctly in
  hostile situations. "correctly" no longer means just getting
  the functional aspects of the program correct, but also means
  ensuring privacy and integrity of data transferred, access
  only to legitimate users and other issues.
</p>
<p class="zh">
应用程序应当在复杂的互联网环境中仍然可以正确工作。“正确”不光意味着程序功能的正确，同时还意味着要确保数据传输过程中的保密性和完整性，甚至只允许合法用户进行访问和其它问题。
</p>
<p class="en">
  This of course makes your programs much more complex. There are
  <em>difficult</em> and <em>subtle</em> computing problems involved
  in making applications secure. Attempts to do it yourself (such as
  making up your own encryption libraries) are usually doomed
  to failure. Instead, you need to make use of libraries designed
  by security professionals
</p>
<p class="zh">
这自然使得编程更加复杂。在构建安全应用程序的过程中，会出现很<em>复杂</em>和<em>微妙</em>的问题。如果你想自己这样做(如实现一个自有安全库)，通常都会以失败而告终。相反，你需要使用安全专家设计的安全库。
</p>
<h2 id="heading_toc_j_1" tabindex="-1" class="en"> ISO security architecture </h2>
<h2 id="heading_toc_j_1" tabindex="-1" class="zh"> ISO 安全架构 </h2>
<p class="en">
  The ISO OSI (open systems interconnect) seven-layer model of
  distributed systems is well known and is repeated in this
  figure: <br>
  <img src="../Images/iso.gif">
</p>
<p class="zh">
ISO OSI（开放系统互连）七层模型分布式系统是众所周知的，在此重复如下图：<br>
  <img src="../Images/iso.gif">
</p>
<p class="en">
  What is less well known is that ISO built a whole series of
  documents upon this architecture. For our purposes here, the most
  important is the ISO Security Architecture model, ISO 7498-2.
</p>
<p class="zh">
少为人知的是，ISO在此架构的基础上建立了一系列完整的文档。而我们这里最重要的是ISO安全体系结构模型（ISO Security Architecture model）ISO 7498-2。
</p>
<h3 id="heading_toc_j_2" tabindex="-1" class="en"> Functions and levels </h3>
<h3 id="heading_toc_j_2" tabindex="-1" class="zh"> 功能层次 </h3>

<p class="en">
  The principal functions required of a security system are
</p>
<p class="zh">
主要的安全系统功能
</p>
<ul class="en">
<li>
  Authentication - proof of identity
</li>
<li>
  Data integrity  - data is not tampered with
</li>
<li>
  Confidentiality - data is not exposed to others
</li>
<li>
  Notarization/signature
</li>
<li>
  Access control
</li>
<li>
  Assurance/availability
</li>
</ul>
<ul class="zh">
<li>
  认证 - 身份校验文件
</li>
<li>
  数据完整性 - 数据不被篡改
</li>
<li>
  保密 - 数据不能暴露给他人
</li>
<li>
  公证/签名
</li>
<li>
  访问控制
</li>
<li>
  保证/可用性
</li>
</ul>
<p></p>

<p class="en">
  These are required at the following levels of the OSI stack:
</p>
<p class="zh">
  必须的OSI协议栈
</p>
<ul class="en">
    <li>
      Peer entity authentication (3, 4, 7)
    </li>
    <li>
      Data origin authentication (3, 4, 7)
    </li>
    <li>
      Access control service (3, 4, 7)
    </li>
    <li>
      Connection confidentiality (1, 2, 3, 4, 6, 7)
    </li>
    <li>
      Connectionless confidentiality (1, 2, 3, 4, 6, 7)
    </li>
    <li>
      Selective field confidentiality (6, 7)
    </li>
    <li>
      Traffic flow confidentiality (1, 3, 7)
    </li>
    <li>
      Connection integrity with recovery (4, 7)
    </li>
    <li>
      Connection integrity without recovery (4, 7)
    </li>
    <li>
      Connection integrity selective field (7)
    </li>
    <li>
      Connectionless integrity selective field (7)
    </li>
    <li>
      Non-repudiation at origin (7)
    </li>
    <li>
      Non-repudiation of receipt (7)
    </li>
 </ul>
 <ul class="zh">
    <li>
      对等实体认证 (3, 4, 7)
    </li>
    <li>
      数据源认证 (3, 4, 7)
    </li>
    <li>
      访问控制服务 (3, 4, 7)
    </li>
    <li>
      连接保密 (1, 2, 3, 4, 6, 7)
    </li>
    <li>
      无连接的保密 (1, 2, 3, 4, 6, 7)
    </li>
    <li>
      选择性字段的保密 (6, 7)
    </li>
    <li>
      传输保密 (1, 3, 7)
    </li>
    <li>
      恢复连接的完整性 (4, 7)
    </li>
    <li>
      不可恢复连接的完整性 (4, 7)
    </li>
    <li>
      选择字段连接完整性 (7)
    </li>
    <li>
      选择字段的无连接完整性 (7)
    </li>
    <li>
      接受源 (7)
    </li>
    <li>
      接受回执 (7)
    </li>
 </ul>
<p></p>

<h3 id="heading_toc_j_3" tabindex="-1" class="en">  Mechanisms </h3>
<h3 id="heading_toc_j_3" tabindex="-1" class="zh">  机制 </h3>
<p></p>
<ul class="en">
    <li>
      Peer entity authentication
      <ul>
  <li>
	  encryption
	</li><li>
	  digital signature
	</li><li>
	  authentication exchange
      </li></ul>
    </li><li>
      Data origin authentication
      <ul>
	<li>
	  encryption
	</li><li>
	  digital signature
      </li></ul>
    </li><li>
      Access control service
      <ul>
	<li>
	  access control lists
	</li><li>
	  passwords
	</li><li>
	  capabilities lists
	</li><li>
	  labels
	</li>
      </ul>

    </li><li>
      Connection confidentiality
      <ul>
	<li>
	  ecryption
	</li><li>
	  routing control
      </li></ul>
    </li><li>
      Connectionless confidelity
      <ul>
	<li>
	  encryption
	</li><li>
	  routing control
      </li></ul>
    </li><li>
      Selective field confidelity
      <ul>
	<li>
	  encryption
      </li></ul>
    </li><li>
      Traffic flow confidelity
      <ul>
	<li>
	  encryption
	</li><li>
	  traffic padding
	</li><li>
	  routing control
      </li></ul>

    </li><li>
      Connection integrity with recovery
      <ul>
	<li>
	  encryption
	</li><li>
	  data integrity
      </li></ul>
    </li><li>
      Connection integrity without recovery
      <ul>
	<li>
	  encryption
	</li><li>
	  data integrity
      </li></ul>
    </li><li>
      Connection integrity selective field
      <ul>
	<li>
	  encryption
	</li><li>
	  data integrity
      </li></ul>
    </li><li>
      Connectionless integrity
      <ul>
	<li>
	  encryption
	</li><li>
	  digital signature
	</li><li>
	  data integrity
      </li></ul>

    </li><li>
      Connectionless integrity selective field
      <ul>
	<li>
	  encryption
	</li><li>
	  digital signature
	</li><li>
	  data integrity
      </li></ul>
    </li><li>
      Non-repudiation at origin
      <ul>
	<li>
	  digital signature
	</li><li>
	  data integrity
	</li><li>
	  notarisation
      </li></ul>
    </li><li>
      Non-repudiation of receipt
      <ul>
	<li>
	  digital signature
	</li><li>
	  data integrity
	</li><li>
	  notarisation
      </li></ul>
  </li></ul>
<ul class="zh">
    <li>
      对等实体认证
      <ul>
		<li>
			加密
		</li><li>
			数字签名
		</li><li>
			交换验证
		</li>
	   </ul>
    </li>
	<li>
      数据源认证
      <ul>
		<li>
			加密
		</li><li>
			数字签名
		</li>
		</ul>
    </li>
	<li>
      访问控制服务
      <ul>
	<li>
	  访问控制列表
	</li><li>
	  密码
	</li><li>
	  范围列表
	</li><li>
	  等级
	</li>
      </ul>
    </li><li>
      连接保密
      <ul>
	<li>
	  密码
	</li><li>
	  路由控制
      </li></ul>
    </li><li>
      无连接的保密
      <ul>
	<li>
	  密码
	</li><li>
	  路由控制
      </li></ul>
    </li><li>
      选择性字段的保密
      <ul>
	<li>
	  密码
      </li></ul>
    </li><li>
      传输保密
      <ul>
	<li>
	  密码
	</li><li>
	  传输填充
	</li><li>
	  路由控制
      </li></ul>

    </li><li>
      恢复连接的完整性
      <ul>
	<li>
	  密码
	</li><li>
	 数据完整性
      </li></ul>
    </li><li>
      不可恢复连接的完整性
      <ul>
	<li>
	  密码
	</li><li>
	  数据完整性
      </li></ul>
    </li><li>
      选择字段连接完整性
      <ul>
	<li>
	  密码
	</li><li>
	  数据完整性
      </li></ul>
    </li><li>
		无连接完整性
      <ul>
	<li>
	  密码
	</li><li>
	  数字签名
	</li><li>
	  数据完整性
      </li></ul>

    </li><li>
      选择字段的无连接完整性
      <ul>
	<li>
	  密码
	</li><li>
	  数字签名
	</li><li>
	  数据完整性
      </li></ul>
    </li><li>
      接受源
      <ul>
	<li>
	  数字签名
	</li><li>
	  数据完整性
	</li><li>
	  公正
      </li></ul>
    </li><li>
      接受回执
      <ul>
	<li>
	  数字签名
	</li><li>
	  数据完整性
	</li><li>
	  公正
      </li></ul>
  </li></ul>
<p></p>

<h2 id="heading_toc_j_4" tabindex="-1" class="en"> Data integrity </h2>
<h2 id="heading_toc_j_4" tabindex="-1" class="zh"> 数据完整性 </h2>
<p class="en">
  Ensuring data integrity means supplying a means of testing that
  the data has not been tampered with. Usually this is done by
  forming a simple number out of the bytes in the data. This process
  is called <em>hashing</em> and the resulting number is called a
  <em>hash</em> or <em>hash value</em>.
</p>
<p class="zh">
确保数据的完整性意味着要提供一个数据未被篡改的测试方法。通常是通过字节数据生成一个简单的数字。这个操作被称为<em>hashing</em>，结果数字成为<em>hash</em>或者<em>hash值</em>。
</p>
<p class="en">
  A naive hashing algorithm is just to sum up all the bytes in the
  data. However, this still allows almost any amount of changing the
  data around and still preserving the hash values. For example,
  an attacker could just swap two bytes. This preserves the hash value,
  but could end up with you owing someone $65,536 instead of $256.
</p>
<p class="zh">
有一个幼稚的hash算法是将数据所有的字节进行总和。然而，这却仍然允许数据在保留hash值不变的情况下对数据进行任意改变。例如，攻击者只需要交换两个字节。这样hash值没有改变，但结果可能是你本来欠别人256美元却变成了65535美元。
</p>
<p class="en">
  Hashing algorithms used for security purposes have to be "strong",
  so that it is very difficult
  for an attacker to find a different sequence of bytes with the same
  hash value. This makes it hard to modify the data to the attacker's
  purposes. Security researchers are constantly testing hash
  algorithms to see if they can break them - that is, find a simple
  way of coming up with byte sequences to match a hash value.
  They have devised a series of <em>cryptographic</em> hashing
  algorithms which are believed to be strong.
</p>
<P class="zh">
用于安全目的的hash算法必须很“强”，这样攻击者才很难在保留相同的hash值时找到一个不同的字节序列。这样攻击者才很难修改数据以达到目的。安全研究人员不断测试是否能攻破hash算法 - 寻找一个简单方法，得到一个字节序列来匹配某个hash值。他们设计了一系列被认为很强的<em>加密</em>hash算法.

</p>
<p class="en">
  Go has support for several hashing algorithms, including
  MD4, MD5, RIPEMD-160, SHA1, SHA224, SHA256, SHA384 and SHA512.
  They all follow the same pattern as far as the Go programmer
  is concerned: a function <code>New</code> (or similar) in
  the appropriate package returns a <code>Hash</code> object
  from the <code>hash</code> package.
</p>
<p class="zh">
Go支持几个hash算法,包括MD4, MD5, RIPEMD-160, SHA1, SHA224, SHA256, SHA384 and SHA512。它们都尽可能按照Go程序员关注的，遵循相同的模式：在适当的包中定义<code>New</code>或类似的方法，返回一个<code>hash</code>包中的<code>Hash</code> 对象。
<p/>
<p class="en">
  A <code>Hash</code> has an <code>io.Writer</code>, and you write
  the data to be hashed to this writer. You can query the number
  of bytes in the hash value by <code>Size</code> and the hash
  value by <code>Sum</code>.
</p>
<p class="zh">
一个<code>Hash</code>结构体拥有一个<code>io.Writer</code>接口，你可以通过writer方法写入被hash的数据.你可以通过<code>Size</code>方法获取hash值的长度，<code>Sum</code>方法返回hash值。
</p>
<p>
  A typical case is MD5 hashing. This uses the <code>md5</code>
  package. The hash value is a 16 byte array. This is typically
  printed out in ASCII form as four hexadecimal numbers, each
  made of 4 bytes. A simple program is
</p>
<p class="zh">
MD5算法是个典型的例子。使用<code>md5</code>包，hash值是一个16位的数组。通常以ASCII形式输出四个由4字节组成的十六进制数。程序如下
</p>
<pre><code><font color="black">
<font color="firebrick">/* MD5Hash
 */
</font>
<font color="purple">package</font> main

<font color="purple">import</font> (
	<font color="DarkRed">"crypto/md5"</font>
	<font color="DarkRed">"fmt"</font>
)

<font color="purple">func</font> main() {
	hash := md5.<font color="blue">New</font>()
	bytes := []<font color="green">byte</font>(<font color="DarkRed">"hello\n"</font>)
	hash.<font color="blue">Write</font>(bytes)
	hashValue := hash.<font color="blue">Sum</font>(nil)
	hashSize := hash.<font color="blue">Size</font>()
	<font color="purple">for</font> n := 0; n &lt; hashSize; n += 4 {
		<font color="purple">var</font> val uint32
		val = uint32(hashValue[n])&lt;&lt;24 +
			uint32(hashValue[n+1])&lt;&lt;16 +
			uint32(hashValue[n+2])&lt;&lt;8 +
			uint32(hashValue[n+3])
		fmt.<font color="blue">Printf</font>(<font color="DarkRed">"%x "</font>, val)
	}
	fmt.<font color="blue">Println</font>()
}
</font></code></pre>
<p class="en">
  which prints "b1946ac9 2492d234 7c6235b4 d2611184"
</p>
<p class="zh">
  输出 "b1946ac9 2492d234 7c6235b4 d2611184"
</p>
<p class="en">
  A variation on this is the HMAC (Keyed-Hash Message Authentication Code)
  which adds a key to the hash algorithm. There is little change in using
  this. To use MD5 hashing along with a key, replace the call to
  <code>New</code> by
</p>
<p class="zh">
在此基础上的一个变化是HMAC(Keyed-Hash Message Authentication Code)，它给hash算法增加了一个key。使用时略有不同。要和key一起使用MD5算法时，可以通过以下形式替换<code>New</code>
</p>
  <code>
    </code></p><pre><code>func NewMD5(key []byte) hash.Hash
    </code></pre><code>
  </code>
<p></p>

<h2 id="heading_toc_j_5" tabindex="-1" class="en"> Symmetric key encryption </h2>
<h2 id="heading_toc_j_5" tabindex="-1" class="zh"> key对称加密 </h2>
<p class="en">
  There are two major mechanisms used for encrypting data.
  The first uses a single key that is the same for both
  encryption and decryption. This key needs to be known to
  both the encrypting and the decrypting agents. How this
  key is transmitted between the agents is not discussed.
</p>
<p class="zh">
数据加密有两种机制。第一种方式是在加密和解密时都使用同一个key。加密方和解密方都需要知道这个key。此处如何在这两者之间传输这个key。
</p>
<p class="en">
  As with hashing, there are many encryption algorithms.
  Many are now known to have weaknesses, and in general
  algorithms become weaker over time as computers get
  faster. Go has support for several symmetric key algorithms
  such as Blowfish and DES.
</p>
<p class="zh">
目前有很多使用hash算法的加密算法。其中很多都有弱点，而且随着时间的推移，计算机越来越快，通用hash算法变得越来越弱。Go已经支持好几个对称加密算法，如Blowfish和DES。
</p>
<p class="en">
  The algorithms are <em>block</em> algorithms. That is they
  work on blocks of data. If you data is not aligned to the
  block size, then you will have to pad it with extra blanks
  at the end.
</p>
<p class="zh">
这些算法都是<em>block</em>算法。因为它们必须基于数据块(block)。如果你的数据不匹配block的大小，那就必须在最后使用空格来填充多余的空间。
</p>
<p class="en">
  Each algorith is represented by a <code>Cipher</code> object.
  This is created by <code>NewCipher</code> in the appropriate
  package, and takes the symmetric key as parameter.
</p>
<p class="zh">
每个算法都被表示为一个<code>Cipher</code>对象。可通过在相应的包中使用对称key作为参数调用<code>NewCipher</code>方法来创建该对象。
</p>
<p class="en">
  Once you have a cipher, you can use it to encrypt and decrypt
  blocks of data. The blocks have to be 8-bit blocks for Blowfish.
  A program to illustrate this is
</p>
<p class="zh">
创建cipher对象后，就能通过它加密和解密数据块。Blowfish需要8位的block，详见以下程序
</p>
<pre><code><font color="black">
<font color="firebrick">/* Blowfish
 */
</font>
<font color="purple">package</font> main

<font color="purple">import</font> (
	<font color="DarkRed">"bytes"</font>
	<font color="DarkRed">"code.google.com/p/go.crypto/blowfish"</font>
	<font color="DarkRed">"fmt"</font>
)

<font color="purple">func</font> main() {
	key := []<font color="green">byte</font>(<font color="DarkRed">"my key"</font>)
	cipher, err := blowfish.<font color="blue">NewCipher</font>(key)
	<font color="purple">if</font> err != nil {
		fmt.<font color="blue">Println</font>(err.<font color="blue">Error</font>())
	}
	src := []<font color="green">byte</font>(<font color="DarkRed">"hello\n\n\n"</font>)
	<font color="purple">var</font> enc [512]<font color="green">byte</font>

	cipher.<font color="blue">Encrypt</font>(enc[0:], src)

	<font color="purple">var</font> decrypt [8]<font color="green">byte</font>
	cipher.<font color="blue">Decrypt</font>(decrypt[0:], enc[0:])
	result := bytes.<font color="blue">NewBuffer</font>(nil)
	result.<font color="blue">Write</font>(decrypt[0:8])
	fmt.<font color="blue">Println</font>(string(result.<font color="blue">Bytes</font>()))
}
</font></code></pre>

<p></p>

<div class="warning">
<p class="en">
  Blowfish is not in the Go 1 distribution. Instead it is on the
  http://code.google.com/p/ site. You have to install it by running
  "go get"
  in a directory where you have source that needs to use it.
</p>
<p class="zh">
Blowfish不在GO 1中，而是在http://code.google.com/p/中。你可以在需要使用它的源码目录下运行“go get”进行安装。
</p>
</div>

<h2 id="heading_toc_j_6" tabindex="-1" class="en"> Public key encryption </h2>
<h2 id="heading_toc_j_6" tabindex="-1" class="zh"> 公钥加密 </h2>

<p class="en">
Public key encryption and decryption requires <em>two</em> keys:
one to encrypt and a second one to decrypt. The encryption key
is usually made public in some way so that anyone can encrypt
messages to you. The decryption key must stay private, otherwise
everyon would be able to decrypt those messages! Public key
systems aer asymmetric, with different keys for different uses.
</p>
<p class="zh">
公钥加密和解密需要<em>两个</em>key：一个用来加密，另一个用来解密。加密key通常是公开的，这样任何人都可以给你发送加密数据。解密key必须保密，否则任何人都可以解密数据。公钥系统是非对称的，不同的key有不同的用途。
</p>
<p class="en">
There are many public key encryption systems supported by Go.
A typical one is the RSA scheme.
</p>
<P class="zh">
Go支持很多公钥加密系统，RSA就是一个典型的例子。
</p>
<p class="en">
  A program generating RSA private and public keys is
</p>
<p class="zh">
  下面是一个生成RSA公钥和私钥的程序
</p>
<pre><code><font color="black">
<font color="firebrick">/* GenRSAKeys
 */
</font>
<font color="purple">package</font> main

<font color="purple">import</font> (
	<font color="DarkRed">"crypto/rand"</font>
	<font color="DarkRed">"crypto/rsa"</font>
	<font color="DarkRed">"crypto/x509"</font>
	<font color="DarkRed">"encoding/gob"</font>
	<font color="DarkRed">"encoding/pem"</font>
	<font color="DarkRed">"fmt"</font>
	<font color="DarkRed">"os"</font>
)

<font color="purple">func</font> main() {
	reader := rand.<font color="blue">Reader</font>
	bitSize := 512
	key, err := rsa.<font color="blue">GenerateKey</font>(reader, bitSize)
	checkError(err)

	fmt.<font color="blue">Println</font>(<font color="DarkRed">"Private key primes"</font>, key.<font color="blue">Primes</font>[0].<font color="blue">String</font>(), key.<font color="blue">Primes</font>[1].<font color="blue">String</font>())
	fmt.<font color="blue">Println</font>(<font color="DarkRed">"Private key exponent"</font>, key.<font color="darkmagenta">D</font>.<font color="blue">String</font>())

	publicKey := key.<font color="blue">PublicKey</font>
	fmt.<font color="blue">Println</font>(<font color="DarkRed">"Public key modulus"</font>, publicKey.<font color="darkmagenta">N</font>.<font color="blue">String</font>())
	fmt.<font color="blue">Println</font>(<font color="DarkRed">"Public key exponent"</font>, publicKey.<font color="darkmagenta">E</font>)

	saveGobKey(<font color="DarkRed">"private.key"</font>, key)
	saveGobKey(<font color="DarkRed">"public.key"</font>, publicKey)

	savePEMKey(<font color="DarkRed">"private.pem"</font>, key)
}

<font color="purple">func</font> saveGobKey(fileName string, key <font color="purple">interface</font>{}) {
	outFile, err := os.<font color="blue">Create</font>(fileName)
	checkError(err)
	encoder := gob.<font color="blue">NewEncoder</font>(outFile)
	err = encoder.<font color="blue">Encode</font>(key)
	checkError(err)
	outFile.<font color="blue">Close</font>()
}

<font color="purple">func</font> savePEMKey(fileName string, key *rsa.<font color="blue">PrivateKey</font>) {

	outFile, err := os.<font color="blue">Create</font>(fileName)
	checkError(err)

	<font color="purple">var</font> privateKey = &amp;pem.<font color="blue">Block</font>{<font color="blue">Type</font>: <font color="DarkRed">"RSA PRIVATE KEY"</font>,
		<font color="blue">Bytes</font>: x509.<font color="blue">MarshalPKCS1PrivateKey</font>(key)}

	pem.<font color="blue">Encode</font>(outFile, privateKey)

	outFile.<font color="blue">Close</font>()
}

<font color="purple">func</font> checkError(err error) {
	<font color="purple">if</font> err != nil {
		fmt.<font color="blue">Println</font>(<font color="DarkRed">"Fatal error "</font>, err.<font color="blue">Error</font>())
		os.<font color="blue">Exit</font>(1)
	}
}
</font></code></pre>

<p></p>

<p class="en">
  The program also saves the certificates using <code>gob</code>
  serialisation. They can be read back by this program:
</p>
<p class="zh">
  程序通过<code>gob</code>序列化保存证书。也可以取回证书:
</p>
<pre><code><font color="black">
<font color="firebrick">/* LoadRSAKeys
 */
</font>
<font color="purple">package</font> main

<font color="purple">import</font> (
	<font color="DarkRed">"crypto/rsa"</font>
	<font color="DarkRed">"encoding/gob"</font>
	<font color="DarkRed">"fmt"</font>
	<font color="DarkRed">"os"</font>
)

<font color="purple">func</font> main() {
	<font color="purple">var</font> key rsa.<font color="blue">PrivateKey</font>
	loadKey(<font color="DarkRed">"private.key"</font>, &amp;key)

	fmt.<font color="blue">Println</font>(<font color="DarkRed">"Private key primes"</font>, key.<font color="blue">Primes</font>[0].<font color="blue">String</font>(), key.<font color="blue">Primes</font>[1].<font color="blue">String</font>())
	fmt.<font color="blue">Println</font>(<font color="DarkRed">"Private key exponent"</font>, key.<font color="darkmagenta">D</font>.<font color="blue">String</font>())

	<font color="purple">var</font> publicKey rsa.<font color="blue">PublicKey</font>
	loadKey(<font color="DarkRed">"public.key"</font>, &amp;publicKey)

	fmt.<font color="blue">Println</font>(<font color="DarkRed">"Public key modulus"</font>, publicKey.<font color="darkmagenta">N</font>.<font color="blue">String</font>())
	fmt.<font color="blue">Println</font>(<font color="DarkRed">"Public key exponent"</font>, publicKey.<font color="darkmagenta">E</font>)
}

<font color="purple">func</font> loadKey(fileName string, key <font color="purple">interface</font>{}) {
	inFile, err := os.<font color="blue">Open</font>(fileName)
	checkError(err)
	decoder := gob.<font color="blue">NewDecoder</font>(inFile)
	err = decoder.<font color="blue">Decode</font>(key)
	checkError(err)
	inFile.<font color="blue">Close</font>()
}

<font color="purple">func</font> checkError(err error) {
	<font color="purple">if</font> err != nil {
		fmt.<font color="blue">Println</font>(<font color="DarkRed">"Fatal error "</font>, err.<font color="blue">Error</font>())
		os.<font color="blue">Exit</font>(1)
	}
}
</font></code></pre>

<p></p>

<!--
<h3> PEM </h3>
<p>

  <code>
    <pre>
var pemPrivateKey = `-----BEGIN RSA PRIVATE KEY-----
MIIBOgIBAAJBALKZD0nEffqM1ACuak0bijtqE2QrI/KLADv7l3kK3ppMyCuLKoF0
fd7Ai2KW5ToIwzFofvJcS/STa6HA5gQenRUCAwEAAQJBAIq9amn00aS0h/CrjXqu
/ThglAXJmZhOMPVn4eiu7/ROixi9sex436MaVeMqSNf7Ex9a8fRNfWss7Sqd9eWu
RTUCIQDasvGASLqmjeffBNLTXV2A5g4t+kLVCpsEIZAycV5GswIhANEPLmax0ME/
EO+ZJ79TJKN5yiGBRsv5yvx5UiHxajEXAiAhAol5N4EUyq6I9w1rYdhPMGpLfk7A
IU2snfRJ6Nq2CQIgFrPsWRCkV+gOYcajD17rEqmuLrdIRexpg8N1DOSXoJ8CIGlS
tAboUGBxTDq3ZroNism3DaMIbKPyYrAqhKov1h5V
-----END RSA PRIVATE KEY-----
`

func bigFromString(s string) *big.Int {
        ret := new(big.Int)
        ret.SetString(s, 10)
        return ret
}

var rsaPrivateKey = &rsa.PrivateKey{
        PublicKey: rsa.PublicKey{
                N: bigFromString("9353930466774385905609975137998169297361893554
14998671685329502257853572497967725295852446635047121036783518748074826886427746
4700638583474144061408845077"),
                E: 65537,
        },
        D: bigFromString("726639843132811634405769937974922253227934392381906363
94970490393898993285385430876577337665541558398345195294398516730148002612857577
59040931985506583861"),
        P: bigFromString("989203665480846436017288690555926508355729509322669674
61790948584315647051443"),
        Q: bigFromString("945602083088470157474985238840633946716066719049446663
60068158221458669711639"),
}

        block, _ := pem.Decode([]byte(pemPrivateKey))
        priv, err := ParsePKCS1PrivateKey(block.Bytes)
    </pre>
  </code>
</p>
-->

<h2 id="heading_toc_j_7" tabindex="-1" class="en"> X.509 certificates </h2>
<h2 id="heading_toc_j_7" tabindex="-1" class="zh"> X.509 证书 </h2>
<p class="en">
  A Public Key Infrastructure (PKI) is a framework for a collection
  of public keys, along with additional information such as
  owner name and location, and links between them giving some
  sort of approval mechanism.
</p>
<p class="zh">
公钥基础架构（PKI）是一个公钥集合框架，它连同附加信息，如所有者名称和位置，以及它们之间的联系提供了一些审批机制。
</p>
<p class="en">
  The principal PKI in use today is based on X.509 certificates.
  For example, web browsers use them to verify the identity
  of web sites.
</p>
<p class="zh">
目前主要使用的PKI是就是基于X.509证书的。例如浏览器使用它验证站点的身份。
</p>
<p class="en">
  An example program to generate a self-signed X.509 certificate
  for my web site and store it in a <code>.cer</code> file is
</p>
<p class="zh">
下面的程序是为自己的站点生成自签名X.509证书并保存到一个<code>.cer</code>文件中
</p>
<pre><code><font color="black">
<font color="firebrick">/* GenX509Cert
 */
</font>
<font color="purple">package</font> main

<font color="purple">import</font> (
	<font color="DarkRed">"crypto/rand"</font>
	<font color="DarkRed">"crypto/rsa"</font>
	<font color="DarkRed">"crypto/x509"</font>
	<font color="DarkRed">"crypto/x509/pkix"</font>
	<font color="DarkRed">"encoding/gob"</font>
	<font color="DarkRed">"encoding/pem"</font>
	<font color="DarkRed">"fmt"</font>
	<font color="DarkRed">"math/big"</font>
	<font color="DarkRed">"os"</font>
	<font color="DarkRed">"time"</font>
)

<font color="purple">func</font> main() {
	random := rand.<font color="blue">Reader</font>

	<font color="purple">var</font> key rsa.<font color="blue">PrivateKey</font>
	loadKey(<font color="DarkRed">"private.key"</font>, &amp;key)

	now := time.<font color="blue">Now</font>()
	then := now.<font color="blue">Add</font>(60 * 60 * 24 * 365 * 1000 * 1000 * 1000) <font color="firebrick">// one year
</font>	template := x509.<font color="blue">Certificate</font>{
		<font color="blue">SerialNumber</font>: big.<font color="blue">NewInt</font>(1),
		<font color="blue">Subject</font>: pkix.<font color="blue">Name</font>{
			<font color="blue">CommonName</font>:   <font color="DarkRed">"jan.newmarch.name"</font>,
			<font color="blue">Organization</font>: []string{<font color="DarkRed">"Jan Newmarch"</font>},
		},
		<font color="firebrick">//	NotBefore: time.Unix(now, 0).UTC(),
</font>		<font color="firebrick">//	NotAfter:  time.Unix(now+60*60*24*365, 0).UTC(),
</font>		<font color="blue">NotBefore</font>: now,
		<font color="blue">NotAfter</font>:  then,

		<font color="blue">SubjectKeyId</font>: []<font color="green">byte</font>{1, 2, 3, 4},
		<font color="blue">KeyUsage</font>:     x509.<font color="blue">KeyUsageCertSign</font> | x509.<font color="blue">KeyUsageKeyEncipherment</font> | x509.<font color="blue">KeyUsageDigitalSignature</font>,

		<font color="blue">BasicConstraintsValid</font>: true,
		<font color="blue">IsCA</font>:                  true,
		<font color="blue">DNSNames</font>:              []string{<font color="DarkRed">"jan.newmarch.name"</font>, <font color="DarkRed">"localhost"</font>},
	}
	derBytes, err := x509.<font color="blue">CreateCertificate</font>(random, &amp;template,
		&amp;template, &amp;key.<font color="blue">PublicKey</font>, &amp;key)
	checkError(err)

	certCerFile, err := os.<font color="blue">Create</font>(<font color="DarkRed">"jan.newmarch.name.cer"</font>)
	checkError(err)
	certCerFile.<font color="blue">Write</font>(derBytes)
	certCerFile.<font color="blue">Close</font>()

	certPEMFile, err := os.<font color="blue">Create</font>(<font color="DarkRed">"jan.newmarch.name.pem"</font>)
	checkError(err)
	pem.<font color="blue">Encode</font>(certPEMFile, &amp;pem.<font color="blue">Block</font>{<font color="blue">Type</font>: <font color="DarkRed">"CERTIFICATE"</font>, <font color="blue">Bytes</font>: derBytes})
	certPEMFile.<font color="blue">Close</font>()

	keyPEMFile, err := os.<font color="blue">Create</font>(<font color="DarkRed">"private.pem"</font>)
	checkError(err)
	pem.<font color="blue">Encode</font>(keyPEMFile, &amp;pem.<font color="blue">Block</font>{<font color="blue">Type</font>: <font color="DarkRed">"RSA PRIVATE KEY"</font>,
		<font color="blue">Bytes</font>: x509.<font color="blue">MarshalPKCS1PrivateKey</font>(&amp;key)})
	keyPEMFile.<font color="blue">Close</font>()
}

<font color="purple">func</font> loadKey(fileName string, key <font color="purple">interface</font>{}) {
	inFile, err := os.<font color="blue">Open</font>(fileName)
	checkError(err)
	decoder := gob.<font color="blue">NewDecoder</font>(inFile)
	err = decoder.<font color="blue">Decode</font>(key)
	checkError(err)
	inFile.<font color="blue">Close</font>()
}

<font color="purple">func</font> checkError(err error) {
	<font color="purple">if</font> err != nil {
		fmt.<font color="blue">Println</font>(<font color="DarkRed">"Fatal error "</font>, err.<font color="blue">Error</font>())
		os.<font color="blue">Exit</font>(1)
	}
}
</font></code></pre>

<p></p>

<p class="en">
  This can then be read back in by
</p>
<p class="zh">
下面这个程序可以读取这个证书
</p>
<pre><code><font color="black">
<font color="firebrick">/* GenX509Cert
 */
</font>
<font color="purple">package</font> main

<font color="purple">import</font> (
	<font color="DarkRed">"crypto/x509"</font>
	<font color="DarkRed">"fmt"</font>
	<font color="DarkRed">"os"</font>
)

<font color="purple">func</font> main() {
	certCerFile, err := os.<font color="blue">Open</font>(<font color="DarkRed">"jan.newmarch.name.cer"</font>)
	checkError(err)
	derBytes := make([]<font color="green">byte</font>, 1000) <font color="firebrick">// bigger than the file
</font>	count, err := certCerFile.<font color="blue">Read</font>(derBytes)
	checkError(err)
	certCerFile.<font color="blue">Close</font>()

	<font color="firebrick">// trim the bytes to actual length in call
</font>	cert, err := x509.<font color="blue">ParseCertificate</font>(derBytes[0:count])
	checkError(err)

	fmt.<font color="blue">Printf</font>(<font color="DarkRed">"Name %s\n"</font>, cert.<font color="blue">Subject</font>.<font color="blue">CommonName</font>)
	fmt.<font color="blue">Printf</font>(<font color="DarkRed">"Not before %s\n"</font>, cert.<font color="blue">NotBefore</font>.<font color="blue">String</font>())
	fmt.<font color="blue">Printf</font>(<font color="DarkRed">"Not after %s\n"</font>, cert.<font color="blue">NotAfter</font>.<font color="blue">String</font>())

}

<font color="purple">func</font> checkError(err error) {
	<font color="purple">if</font> err != nil {
		fmt.<font color="blue">Println</font>(<font color="DarkRed">"Fatal error "</font>, err.<font color="blue">Error</font>())
		os.<font color="blue">Exit</font>(1)
	}
}
</font></code></pre>

<p></p>

<h2 id="heading_toc_j_8" tabindex="-1" class="en"> TLS </h2>
<h2 id="heading_toc_j_8" tabindex="-1" class="zh"> TLS</h2>
<p class="en">
Encryption/decryption schemes are of limited use if you have to do
all the heavy lifting yourself. The most popular mechanism on the internet
to give support for encrypted message passing is currently TLS
(Transport Layer Security) which was formerly SSL
(Secure Sockets Layer).
</p>
<p class="zh">
如果自己实现所有的细节，加解密的方案在使用上是有限制的。当前互联网上最流行的加密消息传输方案是TLS（Transport Layer Security安全传输层），其前身为SSL（Secure Sockets Layer安全套接字层）。
</p>
<p class="en">
In TLS, a client and a server negotiate identity using X.509 certificates.
One this is complete, a secret key is invented between them, and all
encryption/decryption is done using this key. The negotiation is
relatively slow, but once complete a faster private key mechanism is used.
</p>
<p class="zh"></p>
在TLS中，客户端和服务器之间使用X.509证书进行身份验证。身份验证完成后，两者之间会生成一个密钥，所有的加密和解密过程都使用这个密钥。虽然客户端和服务端协商的过程相对较慢，但一旦完成就会使用一个较快的私钥机制。
<p class="en">
  A server is
</p>
<p class="zh">
服务器端程序
</p>
<pre><code><font color="black">
<font color="firebrick">/* TLSEchoServer
 */
</font><font color="purple">package</font> main

<font color="purple">import</font> (
	<font color="DarkRed">"crypto/rand"</font>
	<font color="DarkRed">"crypto/tls"</font>
	<font color="DarkRed">"fmt"</font>
	<font color="DarkRed">"net"</font>
	<font color="DarkRed">"os"</font>
	<font color="DarkRed">"time"</font>
)

<font color="purple">func</font> main() {

	cert, err := tls.<font color="blue">LoadX509KeyPair</font>(<font color="DarkRed">"jan.newmarch.name.pem"</font>, <font color="DarkRed">"private.pem"</font>)
	checkError(err)
	config := tls.<font color="blue">Config</font>{<font color="blue">Certificates</font>: []tls.<font color="blue">Certificate</font>{cert}}

	now := time.<font color="blue">Now</font>()
	config.<font color="blue">Time</font> = <font color="purple">func</font>() time.<font color="blue">Time</font> { <font color="purple">return</font> now }
	config.<font color="blue">Rand</font> = rand.<font color="blue">Reader</font>

	service := <font color="DarkRed">"0.0.0.0:1200"</font>

	listener, err := tls.<font color="blue">Listen</font>(<font color="DarkRed">"tcp"</font>, service, &amp;config)
	checkError(err)
	fmt.<font color="blue">Println</font>(<font color="DarkRed">"Listening"</font>)
	<font color="purple">for</font> {
		conn, err := listener.<font color="blue">Accept</font>()
		<font color="purple">if</font> err != nil {
			fmt.<font color="blue">Println</font>(err.<font color="blue">Error</font>())
			<font color="purple">continue</font>
		}
		fmt.<font color="blue">Println</font>(<font color="DarkRed">"Accepted"</font>)
		go handleClient(conn)
	}
}

<font color="purple">func</font> handleClient(conn net.<font color="blue">Conn</font>) {
	defer conn.<font color="blue">Close</font>()

	<font color="purple">var</font> buf [512]<font color="green">byte</font>
	<font color="purple">for</font> {
		fmt.<font color="blue">Println</font>(<font color="DarkRed">"Trying to read"</font>)
		n, err := conn.<font color="blue">Read</font>(buf[0:])
		<font color="purple">if</font> err != nil {
			fmt.<font color="blue">Println</font>(err)
		}
		<font color="darkmagenta">_</font>, err2 := conn.<font color="blue">Write</font>(buf[0:n])
		<font color="purple">if</font> err2 != nil {
			<font color="purple">return</font>
		}
	}
}

<font color="purple">func</font> checkError(err error) {
	<font color="purple">if</font> err != nil {
		fmt.<font color="blue">Println</font>(<font color="DarkRed">"Fatal error "</font>, err.<font color="blue">Error</font>())
		os.<font color="blue">Exit</font>(1)
	}
}
</font></code></pre>

<p></p>

<p class="en">
  The server works  with the following client:
</p>
<p class="zh">
与服务器端程序对应的客户端程序:
</p>
<pre><code><font color="black">
<font color="firebrick">/* TLSEchoClient
 */
</font><font color="purple">package</font> main

<font color="purple">import</font> (
	<font color="DarkRed">"fmt"</font>
	<font color="DarkRed">"os"</font>
	<font color="DarkRed">"crypto/tls"</font>
)

<font color="purple">func</font> main() {
	<font color="purple">if</font> len(os.<font color="blue">Args</font>) != 2 {
		fmt.<font color="blue">Println</font>(<font color="DarkRed">"Usage: "</font>, os.<font color="blue">Args</font>[0], <font color="DarkRed">"host:port"</font>)
		os.<font color="blue">Exit</font>(1)
	}
	service := os.<font color="blue">Args</font>[1]

	conn, err := tls.<font color="blue">Dial</font>(<font color="DarkRed">"tcp"</font>, service, nil)
	checkError(err)

	<font color="purple">for</font> n := 0; n &lt; 10; n++ {
		fmt.<font color="blue">Println</font>(<font color="DarkRed">"Writing..."</font>)
		conn.<font color="blue">Write</font>([]<font color="green">byte</font>(<font color="DarkRed">"Hello "</font> + string(n+48)))

		<font color="purple">var</font> buf [512]<font color="green">byte</font>
		n, err := conn.<font color="blue">Read</font>(buf[0:])
		checkError(err)

		fmt.<font color="blue">Println</font>(string(buf[0:n]))
	}
	os.<font color="blue">Exit</font>(0)
}

<font color="purple">func</font> checkError(err error) {
	<font color="purple">if</font> err != nil {
		fmt.<font color="blue">Println</font>(<font color="DarkRed">"Fatal error "</font>, err.<font color="blue">Error</font>())
		os.<font color="blue">Exit</font>(1)
	}
}
</font></code></pre>

<p></p>

<h2 id="heading_toc_j_9" tabindex="-1" class="en"> Conclusion </h2>
<h2 id="heading_toc_j_9" tabindex="-1" class="zh"> 结论 </h2>
<p class="en">
Security is a huge area in itself, and in this chapter we have barely touched on it.
However, the major concepts have been covered. What has not been stressed is how
much security needs to be built into the design phase: security as an afterthought
is nearly always a failure.
</p>
<p class="zh">
安全本身是一个巨大的领域，在本章中，我们几乎没有触及，但已经覆盖了主要的概念。尚未强调的是，需要在设计阶段如何考虑安全构建：亡羊补牢几乎是没有意义的。
</p>
  <p>Copyright Jan Newmarch, jan@newmarch.name</p>

  <p>If you like this book, please contribute using Flattr <a class="FlattrButton sgc-8" href="http://jan.newmarch.name/go/index.html"></a><br />
  or donate using PayPal</p>

  <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
    <input name="cmd" type="hidden" value="_s-xclick" /> <input name="encrypted" type="hidden" value="-----BEGIN PKCS7-----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-----END PKCS7----- " /> <input alt="PayPal - The safer, easier way to pay online." border="0" name="submit" src="https://www.paypalobjects.com/WEBSCR-640-20110401-1/en_AU/i/btn/btn_donateCC_LG.gif" type="image" /> <img alt="" border="0" height="1" src="https://www.paypalobjects.com/WEBSCR-640-20110401-1/en_AU/i/scr/pixel.gif" width="1" />
  </form>
</body>
</html>
